package gemini.castor.ui.client.mvp.gin;

import gemini.castor.ui.client.mvp.PlaceRequestManager;
import gemini.castor.ui.client.mvp.container.CastorWidgetContainerPresenter;
import gemini.castor.ui.client.mvp.single.CastorWidgetPresenter;
import gemini.castor.ui.client.page.RootPresenter;
import gemini.castor.ui.client.page.RootView;
import gemini.castor.ui.client.page.content.account.accountinfo.AccountInfoPresenter;
import gemini.castor.ui.client.page.content.account.accountinfo.AccountInfoView;
import gemini.castor.ui.client.page.content.account.accountinfo.form.AccountInfoFormPresenter;
import gemini.castor.ui.client.page.content.account.accountinfo.form.AccountInfoFormView;
import gemini.castor.ui.client.page.content.account.mydownline.MyDownlinePresenter;
import gemini.castor.ui.client.page.content.account.mydownline.MyDownlineView;
import gemini.castor.ui.client.page.content.account.mydownline.form.MyDownlineFormPresenter;
import gemini.castor.ui.client.page.content.account.mydownline.form.MyDownlineFormView;
import gemini.castor.ui.client.page.content.account.myorder.MyOrderPresenter;
import gemini.castor.ui.client.page.content.account.myorder.MyOrderView;
import gemini.castor.ui.client.page.content.account.myorder.form.MyOrderFormPresenter;
import gemini.castor.ui.client.page.content.account.myorder.form.MyOrderFormView;
import gemini.castor.ui.client.page.content.account.mysponsor.MySponsorPresenter;
import gemini.castor.ui.client.page.content.account.mysponsor.MySponsorView;
import gemini.castor.ui.client.page.content.account.mysponsor.form.MySponsorFormPresenter;
import gemini.castor.ui.client.page.content.account.mysponsor.form.MySponsorFormView;
import gemini.castor.ui.client.page.content.account.volumepoint.VolumePointPresenter;
import gemini.castor.ui.client.page.content.account.volumepoint.VolumePointView;
import gemini.castor.ui.client.page.content.account.volumepoint.form.VolumePointFormPresenter;
import gemini.castor.ui.client.page.content.account.volumepoint.form.VolumePointFormView;
import gemini.castor.ui.client.page.content.customer.careschedule.CareSchedulePresenter;
import gemini.castor.ui.client.page.content.customer.careschedule.CareScheduleView;
import gemini.castor.ui.client.page.content.customer.careschedule.form.CareScheduleFormPresenter;
import gemini.castor.ui.client.page.content.customer.careschedule.form.CareScheduleFormView;
import gemini.castor.ui.client.page.content.customer.customerlist.CustomerPresenter;
import gemini.castor.ui.client.page.content.customer.customerlist.CustomerView;
import gemini.castor.ui.client.page.content.customer.customerlist.edit.CustomerEditPresenter;
import gemini.castor.ui.client.page.content.customer.customerlist.edit.CustomerEditView;
import gemini.castor.ui.client.page.content.customer.customerlist.list.CustomerListPresenter;
import gemini.castor.ui.client.page.content.customer.customerlist.list.CustomerListView;
import gemini.castor.ui.client.page.content.home.apply.ApplyPresenter;
import gemini.castor.ui.client.page.content.home.apply.ApplyView;
import gemini.castor.ui.client.page.content.home.apply.checkout.CheckOutFormPresenter;
import gemini.castor.ui.client.page.content.home.apply.checkout.CheckOutFormView;
import gemini.castor.ui.client.page.content.home.apply.contractagreement.ContractAgreementFormPresenter;
import gemini.castor.ui.client.page.content.home.apply.contractagreement.ContractAgreementFormView;
import gemini.castor.ui.client.page.content.home.apply.distributorid.DistributorIDFormPresenter;
import gemini.castor.ui.client.page.content.home.apply.distributorid.DistributorIDFormView;
import gemini.castor.ui.client.page.content.home.apply.personalinfo.PersonalInfoFormPresenter;
import gemini.castor.ui.client.page.content.home.apply.personalinfo.PersonalInfoFormView;
import gemini.castor.ui.client.page.content.home.register.RegisterPresenter;
import gemini.castor.ui.client.page.content.home.register.RegisterView;
import gemini.castor.ui.client.page.content.home.register.confirminfo.ConfirmInfoFormPresenter;
import gemini.castor.ui.client.page.content.home.register.confirminfo.ConfirmInfoFormView;
import gemini.castor.ui.client.page.content.home.register.distributorid.DistributorIDPresenter;
import gemini.castor.ui.client.page.content.home.register.distributorid.DistributorIDView;
import gemini.castor.ui.client.page.content.home.register.inputaccount.InputAccountFormPresenter;
import gemini.castor.ui.client.page.content.home.register.inputaccount.InputAccountFormView;
import gemini.castor.ui.client.page.content.home.search.SearchPresenter;
import gemini.castor.ui.client.page.content.home.search.SearchView;
import gemini.castor.ui.client.page.content.home.search.form.SearchFormPresenter;
import gemini.castor.ui.client.page.content.home.search.form.SearchFormView;
import gemini.castor.ui.client.page.content.information.aboutcompany.AboutCompanyPresenter;
import gemini.castor.ui.client.page.content.information.aboutcompany.AboutCompanyView;
import gemini.castor.ui.client.page.content.information.aboutcompany.form.AboutCompanyFormPresenter;
import gemini.castor.ui.client.page.content.information.aboutcompany.form.AboutCompanyFormView;
import gemini.castor.ui.client.page.content.information.aboutproduct.AboutProductPresenter;
import gemini.castor.ui.client.page.content.information.aboutproduct.AboutProductView;
import gemini.castor.ui.client.page.content.information.aboutproduct.form.AboutProductFormPresenter;
import gemini.castor.ui.client.page.content.information.aboutproduct.form.AboutProductFormView;
import gemini.castor.ui.client.page.content.information.bussinessmethod.BussinessMethodsPresenter;
import gemini.castor.ui.client.page.content.information.bussinessmethod.BussinessMethodsView;
import gemini.castor.ui.client.page.content.information.bussinessmethod.form.BussinessMethodsFormPresenter;
import gemini.castor.ui.client.page.content.information.bussinessmethod.form.BussinessMethodsFormView;
import gemini.castor.ui.client.page.content.information.library.LibraryPresenter;
import gemini.castor.ui.client.page.content.information.library.LibraryView;
import gemini.castor.ui.client.page.content.information.library.form.LibraryFormPresenter;
import gemini.castor.ui.client.page.content.information.library.form.LibraryFormView;
import gemini.castor.ui.client.page.content.information.maketingplan.MaketingPlanPresenter;
import gemini.castor.ui.client.page.content.information.maketingplan.MaketingPlanView;
import gemini.castor.ui.client.page.content.information.maketingplan.form.MaketingPlanFormPresenter;
import gemini.castor.ui.client.page.content.information.maketingplan.form.MaketingPlanFormView;
import gemini.castor.ui.client.page.content.information.stepbystep.StepByStepPresenter;
import gemini.castor.ui.client.page.content.information.stepbystep.StepByStepView;
import gemini.castor.ui.client.page.content.information.stepbystep.form.StepByStepFormPresenter;
import gemini.castor.ui.client.page.content.information.stepbystep.form.StepByStepFormView;
import gemini.castor.ui.client.page.content.information.successstories.SuccessStoriesPresenter;
import gemini.castor.ui.client.page.content.information.successstories.SuccessStoriesView;
import gemini.castor.ui.client.page.content.information.successstories.form.SuccessStoriesFormPresenter;
import gemini.castor.ui.client.page.content.information.successstories.form.SuccessStoriesFormView;
import gemini.castor.ui.client.page.content.office.events.EventsPresenter;
import gemini.castor.ui.client.page.content.office.events.EventsView;
import gemini.castor.ui.client.page.content.office.events.edit.EventsEditPresenter;
import gemini.castor.ui.client.page.content.office.events.edit.EventsEditView;
import gemini.castor.ui.client.page.content.office.events.list.EventsListPresenter;
import gemini.castor.ui.client.page.content.office.events.list.EventsListView;
import gemini.castor.ui.client.page.content.office.messegercenter.MessegerCenterPresenter;
import gemini.castor.ui.client.page.content.office.messegercenter.MessegerCenterView;
import gemini.castor.ui.client.page.content.office.messegercenter.form.MessegerCenterFormPresenter;
import gemini.castor.ui.client.page.content.office.messegercenter.form.MessegerCenterFormView;
import gemini.castor.ui.client.page.content.office.mystory.MyStoryPresenter;
import gemini.castor.ui.client.page.content.office.mystory.MyStoryView;
import gemini.castor.ui.client.page.content.office.mystory.form.MyStoryFormPresenter;
import gemini.castor.ui.client.page.content.office.mystory.form.MyStoryFormView;
import gemini.castor.ui.client.page.content.office.news.NewsPresenter;
import gemini.castor.ui.client.page.content.office.news.NewsView;
import gemini.castor.ui.client.page.content.office.news.form.NewsFormPresenter;
import gemini.castor.ui.client.page.content.office.news.form.NewsFormView;
import gemini.castor.ui.client.page.content.office.promotions.PromotionsPresenter;
import gemini.castor.ui.client.page.content.office.promotions.PromotionsView;
import gemini.castor.ui.client.page.content.office.promotions.form.PromotionsFormPresenter;
import gemini.castor.ui.client.page.content.office.promotions.form.PromotionsFormView;
import gemini.castor.ui.client.page.content.office.recognitions.RecognitionsPresenter;
import gemini.castor.ui.client.page.content.office.recognitions.RecognitionsView;
import gemini.castor.ui.client.page.content.office.recognitions.form.RecognitionsFormPresenter;
import gemini.castor.ui.client.page.content.office.recognitions.form.RecognitionsFormView;
import gemini.castor.ui.client.page.content.office.todolist.TodoListPresenter;
import gemini.castor.ui.client.page.content.office.todolist.TodoListView;
import gemini.castor.ui.client.page.content.office.todolist.form.TodoListFormPresenter;
import gemini.castor.ui.client.page.content.office.todolist.form.TodoListFormView;
import gemini.castor.ui.client.page.content.store.catalog.CatalogPresenter;
import gemini.castor.ui.client.page.content.store.catalog.CatalogView;
import gemini.castor.ui.client.page.content.store.catalog.categorycatalog.CategoryCatalogPresenter;
import gemini.castor.ui.client.page.content.store.catalog.categorycatalog.CategoryCatalogView;
import gemini.castor.ui.client.page.content.store.catalog.productcatalog.ProductCatalogPresenter;
import gemini.castor.ui.client.page.content.store.catalog.productcatalog.ProductCatalogView;
import gemini.castor.ui.client.page.content.store.pricelist.PriceListPresenter;
import gemini.castor.ui.client.page.content.store.pricelist.PriceListView;
import gemini.castor.ui.client.page.content.store.pricelist.pricelistform.PriceListFormPresenter;
import gemini.castor.ui.client.page.content.store.pricelist.pricelistform.PriceListFormView;
import gemini.castor.ui.client.page.content.store.searchproduct.SearchProductPresenter;
import gemini.castor.ui.client.page.content.store.searchproduct.SearchProductView;
import gemini.castor.ui.client.page.content.store.searchproduct.searchproductform.SearchProductFormPresenter;
import gemini.castor.ui.client.page.content.store.searchproduct.searchproductform.SearchProductFormView;
import gemini.castor.ui.client.page.content.store.shoppingcart.ShoppingCartPresenter;
import gemini.castor.ui.client.page.content.store.shoppingcart.ShoppingCartView;
import gemini.castor.ui.client.page.content.store.shoppingcart.cartcheckout.CartCheckOutPresenter;
import gemini.castor.ui.client.page.content.store.shoppingcart.cartcheckout.CartCheckOutView;
import gemini.castor.ui.client.page.content.store.shoppingcart.shoppingcartview.ShoppingCartViewPresenter;
import gemini.castor.ui.client.page.content.store.shoppingcart.shoppingcartview.ShoppingCartViewView;
import gemini.castor.ui.client.page.footer.FooterPresenter;
import gemini.castor.ui.client.page.footer.FooterView;
import gemini.castor.ui.client.page.header.HeaderPresenter;
import gemini.castor.ui.client.page.header.HeaderView;
import ch.elca.gwt.mvp.client.DefaultEventBus;
import ch.elca.gwt.mvp.client.Display;
import ch.elca.gwt.mvp.client.EventBus;
import ch.elca.gwt.mvp.client.place.PlaceManager;

import com.google.gwt.inject.client.AbstractGinModule;
import com.google.inject.Singleton;

public class CastorModule extends AbstractGinModule {

    @Override
    protected void configure() {
    	bind(EventBus.class).to(DefaultEventBus.class).in(Singleton.class);
        bind(PlaceManager.class).in(Singleton.class);
        bind(PlaceRequestManager.class).in(Singleton.class);

        bindPresenters();
    }

    private void bindPresenters() {
    	bindSingleton(RootPresenter.class, RootPresenter.Display.class, RootView.class);
    	bindSingleton(HeaderPresenter.class, HeaderPresenter.Display.class, HeaderView.class);
    	bindSingleton(FooterPresenter.class, FooterPresenter.Display.class, FooterView.class);

    	/********************************************** 
         * Main content
         **********************************************/
        
        // Apply to Distributor
    	bindSingletonContainer(ApplyPresenter.class, ApplyPresenter.Display.class, ApplyView.class);
    	bindSingleton(PersonalInfoFormPresenter.class, PersonalInfoFormPresenter.Display.class, PersonalInfoFormView.class);
    	bindSingleton(DistributorIDFormPresenter.class, DistributorIDFormPresenter.Display.class, DistributorIDFormView.class);
    	bindSingleton(ContractAgreementFormPresenter.class, ContractAgreementFormPresenter.Display.class, ContractAgreementFormView.class);
    	bindSingleton(CheckOutFormPresenter.class, CheckOutFormPresenter.Display.class, CheckOutFormView.class);
    	
    	//Register
    	bindSingletonContainer(RegisterPresenter.class, RegisterPresenter.Display.class, RegisterView.class);
    	bindSingleton(DistributorIDPresenter.class, DistributorIDPresenter.Display.class, DistributorIDView.class);
    	bindSingleton(ConfirmInfoFormPresenter.class, ConfirmInfoFormPresenter.Display.class, ConfirmInfoFormView.class);
    	bindSingleton(InputAccountFormPresenter.class, InputAccountFormPresenter.Display.class, InputAccountFormView.class);
    	
    	//Search some one
    	bindSingletonContainer(SearchPresenter.class, SearchPresenter.Display.class, SearchView.class);
    	bindSingleton(SearchFormPresenter.class, SearchFormPresenter.Display.class, SearchFormView.class);
    	
    	//Product Catalog
    	bindSingletonContainer(CatalogPresenter.class, CatalogPresenter.Display.class, CatalogView.class);
    	bindSingleton(ProductCatalogPresenter.class, ProductCatalogPresenter.Display.class, ProductCatalogView.class);
    	bindSingleton(CategoryCatalogPresenter.class, CategoryCatalogPresenter.Display.class, CategoryCatalogView.class);
    	
    	//Shopping Cart
    	bindSingletonContainer(ShoppingCartPresenter.class, ShoppingCartPresenter.Display.class, ShoppingCartView.class);
    	bindSingleton(ShoppingCartViewPresenter.class, ShoppingCartViewPresenter.Display.class, ShoppingCartViewView.class);
    	bindSingleton(CartCheckOutPresenter.class, CartCheckOutPresenter.Display.class, CartCheckOutView.class);
    	
    	//Search Product
    	bindSingletonContainer(SearchProductPresenter.class, SearchProductPresenter.Display.class, SearchProductView.class);
    	bindSingleton(SearchProductFormPresenter.class, SearchProductFormPresenter.Display.class, SearchProductFormView.class);
    	
    	//Price List
    	bindSingletonContainer(PriceListPresenter.class, PriceListPresenter.Display.class, PriceListView.class);
    	bindSingleton(PriceListFormPresenter.class, PriceListFormPresenter.Display.class, PriceListFormView.class);
    	
    	//Account Info
    	bindSingletonContainer(AccountInfoPresenter.class, AccountInfoPresenter.Display.class, AccountInfoView.class);
    	bindSingleton(AccountInfoFormPresenter.class, AccountInfoFormPresenter.Display.class, AccountInfoFormView.class);
    	
    	//Volume Point
    	bindSingletonContainer(VolumePointPresenter.class, VolumePointPresenter.Display.class, VolumePointView.class);
    	bindSingleton(VolumePointFormPresenter.class, VolumePointFormPresenter.Display.class, VolumePointFormView.class);

    	//My Order
    	bindSingletonContainer(MyOrderPresenter.class, MyOrderPresenter.Display.class, MyOrderView.class);
    	bindSingleton(MyOrderFormPresenter.class, MyOrderFormPresenter.Display.class, MyOrderFormView.class);
    	
    	//My Downline
    	bindSingletonContainer(MyDownlinePresenter.class, MyDownlinePresenter.Display.class, MyDownlineView.class);
    	bindSingleton(MyDownlineFormPresenter.class, MyDownlineFormPresenter.Display.class, MyDownlineFormView.class);
    	
    	//My Order
    	bindSingletonContainer(MySponsorPresenter.class, MySponsorPresenter.Display.class, MySponsorView.class);
    	bindSingleton(MySponsorFormPresenter.class, MySponsorFormPresenter.Display.class, MySponsorFormView.class);
    
    	//My Story
    	bindSingletonContainer(MyStoryPresenter.class, MyStoryPresenter.Display.class,MyStoryView.class);
    	bindSingleton(MyStoryFormPresenter.class, MyStoryFormPresenter.Display.class, MyStoryFormView.class);
    	
    	//Events
    	bindSingletonContainer(EventsPresenter.class, EventsPresenter.Display.class,EventsView.class);
    	bindSingleton(EventsListPresenter.class, EventsListPresenter.Display.class, EventsListView.class);
    	bindSingleton(EventsEditPresenter.class, EventsEditPresenter.Display.class, EventsEditView.class);
    	
    	//Messeger Center
    	bindSingletonContainer(MessegerCenterPresenter.class, MessegerCenterPresenter.Display.class,MessegerCenterView.class);
    	bindSingleton(MessegerCenterFormPresenter.class, MessegerCenterFormPresenter.Display.class, MessegerCenterFormView.class);
    	
    	//News
    	bindSingletonContainer(NewsPresenter.class, NewsPresenter.Display.class,NewsView.class);
    	bindSingleton(NewsFormPresenter.class, NewsFormPresenter.Display.class,NewsFormView.class);
    	
    	//Promotions
    	bindSingletonContainer(PromotionsPresenter.class, PromotionsPresenter.Display.class,PromotionsView.class);
    	bindSingleton(PromotionsFormPresenter.class, PromotionsFormPresenter.Display.class,PromotionsFormView.class);
    	
    	//Recognitions
    	bindSingletonContainer(RecognitionsPresenter.class, RecognitionsPresenter.Display.class,RecognitionsView.class);
    	bindSingleton(RecognitionsFormPresenter.class, RecognitionsFormPresenter.Display.class,RecognitionsFormView.class);
    	
    	//Recognitions
    	bindSingletonContainer(TodoListPresenter.class, TodoListPresenter.Display.class,TodoListView.class);
    	bindSingleton(TodoListFormPresenter.class, TodoListFormPresenter.Display.class,TodoListFormView.class);
    	
        //Care Schedule
    	bindSingletonContainer(CareSchedulePresenter.class, CareSchedulePresenter.Display.class,CareScheduleView.class);
    	bindSingleton(CareScheduleFormPresenter.class, CareScheduleFormPresenter.Display.class,CareScheduleFormView.class);
    	
    	//Customer List
    	bindSingletonContainer(CustomerPresenter.class, CustomerPresenter.Display.class,CustomerView.class);
    	bindSingleton(CustomerListPresenter.class, CustomerListPresenter.Display.class,CustomerListView.class);
    	bindSingleton(CustomerEditPresenter.class, CustomerEditPresenter.Display.class,CustomerEditView.class);
    	
    	//Success Stories
    	bindSingletonContainer(SuccessStoriesPresenter.class, SuccessStoriesPresenter.Display.class,SuccessStoriesView.class);
    	bindSingleton(SuccessStoriesFormPresenter.class, SuccessStoriesFormPresenter.Display.class,SuccessStoriesFormView.class);
    	
    	//Step By Step
    	bindSingletonContainer(StepByStepPresenter.class, StepByStepPresenter.Display.class,StepByStepView.class);
    	bindSingleton(StepByStepFormPresenter.class, StepByStepFormPresenter.Display.class,StepByStepFormView.class);
    	
    	//Maketing Plan
    	bindSingletonContainer(MaketingPlanPresenter.class, MaketingPlanPresenter.Display.class,MaketingPlanView.class);
    	bindSingleton(MaketingPlanFormPresenter.class, MaketingPlanFormPresenter.Display.class,MaketingPlanFormView.class);
    	
    	//Library
    	bindSingletonContainer(LibraryPresenter.class, LibraryPresenter.Display.class,LibraryView.class);
    	bindSingleton(LibraryFormPresenter.class, LibraryFormPresenter.Display.class,LibraryFormView.class);
    	
    	//Bussiness Methods
    	bindSingletonContainer(BussinessMethodsPresenter.class, BussinessMethodsPresenter.Display.class,BussinessMethodsView.class);
    	bindSingleton(BussinessMethodsFormPresenter.class, BussinessMethodsFormPresenter.Display.class,BussinessMethodsFormView.class);

    	//About Company
    	bindSingletonContainer(AboutCompanyPresenter.class, AboutCompanyPresenter.Display.class,AboutCompanyView.class);
    	bindSingleton(AboutCompanyFormPresenter.class, AboutCompanyFormPresenter.Display.class,AboutCompanyFormView.class);
    	
    	//About Product
    	bindSingletonContainer(AboutProductPresenter.class, AboutProductPresenter.Display.class,AboutProductView.class);
    	bindSingleton(AboutProductFormPresenter.class, AboutProductFormPresenter.Display.class,AboutProductFormView.class);

    }

    /**
     * Lets GIN know that it must return the same presenter instance everytime
     * (that means the presenter must be stateless). After that bind the display
     * interface (which is a contract between the presenter and its view) with
     * the view.
     */
    private <D extends Display> void bindSingleton(
            final Class<? extends CastorWidgetPresenter<? extends D>> presenterClass,
            final Class<D> displayClass, final Class<? extends D> viewClass) {
        bind(presenterClass).in(Singleton.class);
        bind(displayClass).to(viewClass);
    }
    
    private <D extends Display> void bindSingletonContainer(
            final Class<? extends CastorWidgetContainerPresenter<? extends D>> presenterClass,
            final Class<D> displayClass, final Class<? extends D> viewClass) {
        bind(presenterClass).in(Singleton.class);
        bind(displayClass).to(viewClass);
    }

    /**
     * Works the same as method <code>bindSingleton</code> except GIN will
     * return a new instance of presenter everytime.
     */
    @SuppressWarnings("unused")
	private <D extends Display> void bindNoneSingleton(
            final Class<? extends CastorWidgetPresenter<? extends D>> presenterClass, final Class<D> displayClass,
            final Class<? extends D> viewClass) {
        bind(presenterClass);
        bind(displayClass).to(viewClass);
    }
}
